/*******************************************************************************
 * Copyright 2019 Microchip FPGA Embedded Systems Solutions.
 *
 * SPDX-License-Identifier: MIT
 *
 * @file phy.h
 * @author Microchip FPGA Embedded Systems Solutions
 * @brief Register bit definitions for MII STA (station management entity)
 * standard interface. All basic MII register bits and enhanced capability
 * register bits are defined.
 * Complies with Clauses 22, 28, 37, 40 of IEEE RFC 802.3
 *
 */

#ifndef PSE_PHY_H
#define PSE_PHY_H
#include "../mss_ethernet_mac/mss_ethernet_mac_types.h"

#ifdef __cplusplus
extern "C" {
#endif

/**************************************************************************/
/* Public definitions                                                     */
/**************************************************************************/
/*------------------------------------------------------------------------------
 * MII register definitions.
 */
/* Generic MII registers. */
#define MII_BMCR                     (0X00U) /* Basic mode control register */
#define MII_BMSR                     (0X01U) /* Basic mode status register  */
#define MII_PHYSID1                  (0X02U) /* PHYS ID 1                   */
#define MII_PHYSID2                  (0X03U) /* PHYS ID 2                   */
#define MII_ADVERTISE                (0X04U) /* Advertisement control reg   */
#define MII_LPA                      (0X05U) /* Link partner ability reg    */
#define MII_EXPANSION                (0X06U) /* Expansion register          */
#define MII_NPAR                     (0X07U)
#define MII_LPNPA                    (0X08U)
#define MII_CTRL1000                 (0X09U) /* 1000BASE-T control          */
#define MII_STAT1000                 (0X0AU) /* 1000BASE-T status           */
#define MII_REGCR                    (0x0DU) /* MDD Access control reg      */
#define MII_ADDAR                    (0x0EU) /* MDD Address or Data reg     */
#define MII_ESTATUS                  (0X0FU) /* Extended Status register    */
#define MII_DCOUNTER                 (0X12U) /* Disconnect counter          */
#define MII_FCSCOUNTER               (0X13U) /* False carrier counter       */
#define MII_EXTEND                   (0X14U) /* extended PHY specific ctrl  */
#define MII_RERRCOUNTER              (0X15U) /* Receive error counter       */
#define MII_SREVISION                (0X16U) /* Silicon revision            */
#define MII_RESV1                    (0X17U) /* Reserved...                 */
#define MII_LBRERROR                 (0X18U) /* Lpback, rx, bypass error    */
#define MII_PHYADDR                  (0X19U) /* PHY address                 */
#define MII_RESV2                    (0X1AU) /* Reserved...                 */
#define MII_TPISTATUS                (0X1BU) /* TPI status for 10mbps       */
#define MII_NCONFIG                  (0X1CU) /* Network interface config    */
#define MII_LMCS                     (0X1DU)
#define MII_PHYCTRL1                 (0X1EU)
#define MII_PHYCTRL2                 (0X1FU)

#define MII_TI_REGCR                 (0X0DU)
#define MII_TI_ADDAR                 (0X0EU)
#define MII_TI_PHYCR                 (0X10U)
#define MII_TI_CTRL                  (0X1FU)
#define MII_TI_SGMIICTL1             (0XD3U)

/* Basic mode control register. */
#define BMCR_RESV                    (0x003FU) /* Unused...                   */
#define BMCR_SPEED1000               (0x0040U) /* MSB of Speed (1000)         */
#define BMCR_CTST                    (0x0080U) /* Collision test              */
#define BMCR_FULLDPLX                (0x0100U) /* Full duplex                 */
#define BMCR_ANRESTART               (0x0200U) /* Auto negotiation restart    */
#define BMCR_ISOLATE                 (0x0400U) /* Disconnect DP83840 from MII */
#define BMCR_PDOWN                   (0x0800U) /* Powerdown the DP83840       */
#define BMCR_ANENABLE                (0x1000U) /* Enable auto negotiation     */
#define BMCR_SPEED100                (0x2000U) /* Select 100Mbps              */
#define BMCR_LOOPBACK                (0x4000U) /* TXD loopback bits           */
#define BMCR_RESET                   (0x8000U) /* Reset the DP83840           */

/* Basic mode status register. */
#define BMSR_ERCAP                   (0x0001U) /* Ext-reg capability          */
#define BMSR_JCD                     (0x0002U) /* Jabber detected             */
#define BMSR_LSTATUS                 (0x0004U) /* Link status                 */
#define BMSR_ANEGCAPABLE             (0x0008U) /* Able to do auto-negotiation */
#define BMSR_RFAULT                  (0x0010U) /* Remote fault detected       */
#define BMSR_ANEGCOMPLETE            (0x0020U) /* Auto-negotiation complete   */
#define BMSR_RESV                    (0x00c0U) /* Unused...                   */
#define BMSR_ESTATEN                 (0x0100U) /* Extended Status in R15 */
#define BMSR_100HALF2                (0x0200U) /* Can do 100BASE-T2 HDX */
#define BMSR_100FULL2                (0x0400U) /* Can do 100BASE-T2 FDX */
#define BMSR_10HALF                  (0x0800U) /* Can do 10mbps, half-duplex  */
#define BMSR_10FULL                  (0x1000U) /* Can do 10mbps, full-duplex  */
#define BMSR_100HALF                 (0x2000U) /* Can do 100mbps, half-duplex */
#define BMSR_100FULL                 (0x4000U) /* Can do 100mbps, full-duplex */
#define BMSR_100BASE4                (0x8000U) /* Can do 100mbps, 4k packets  */

/* Advertisement control register. */
#define ADVERTISE_SLCT               (0x001FU) /* Selector bits               */
#define ADVERTISE_CSMA               (0x0001U) /* Only selector supported     */
#define ADVERTISE_10HALF             (0x0020U) /* Try for 10mbps half-duplex  */
#define ADVERTISE_1000XFULL          (0x0020U) /* Try for 1000BASE-X full-duplex */
#define ADVERTISE_10FULL             (0x0040U) /* Try for 10mbps full-duplex  */
#define ADVERTISE_1000XHALF          (0x0040U) /* Try for 1000BASE-X half-duplex */
#define ADVERTISE_100HALF            (0x0080U) /* Try for 100mbps half-duplex */
#define ADVERTISE_1000XPAUSE         (0x0080U) /* Try for 1000BASE-X pause    */
#define ADVERTISE_100FULL            (0x0100U) /* Try for 100mbps full-duplex */
#define ADVERTISE_1000XPSE_ASYM      (0x0100U) /* Try for 1000BASE-X asym pause */
#define ADVERTISE_100BASE4           (0x0200U) /* Try for 100mbps 4k packets  */
#define ADVERTISE_PAUSE_CAP          (0x0400U) /* Try for pause               */
#define ADVERTISE_PAUSE_ASYM         (0x0800U) /* Try for asymetric pause     */
#define ADVERTISE_RESV               (0x1000U) /* Unused...                   */
#define ADVERTISE_RFAULT             (0x2000U) /* Say we can detect faults    */
#define ADVERTISE_LPACK              (0x4000U) /* Ack link partners response  */
#define ADVERTISE_NPAGE              (0x8000U) /* Next page bit               */

#define ADVERTISE_FULL               (ADVERTISE_100FULL | ADVERTISE_10FULL | ADVERTISE_CSMA)
#define ADVERTISE_ALL                (ADVERTISE_10HALF | ADVERTISE_10FULL | ADVERTISE_100HALF | ADVERTISE_100FULL)

/* Link partner ability register. */
#define LPA_SLCT                     (0x001FU) /* Same as advertise selector  */
#define LPA_10HALF                   (0x0020U) /* Can do 10mbps half-duplex   */
#define LPA_1000XFULL                (0x0020U) /* Can do 1000BASE-X full-duplex */
#define LPA_10FULL                   (0x0040U) /* Can do 10mbps full-duplex   */
#define LPA_1000XHALF                (0x0040U) /* Can do 1000BASE-X half-duplex */
#define LPA_100HALF                  (0x0080U) /* Can do 100mbps half-duplex  */
#define LPA_1000XPAUSE               (0x0080U) /* Can do 1000BASE-X pause     */
#define LPA_100FULL                  (0x0100U) /* Can do 100mbps full-duplex  */
#define LPA_1000XPAUSE_ASYM          (0x0100U) /* Can do 1000BASE-X pause asym*/
#define LPA_100BASE4                 (0x0200U) /* Can do 100mbps 4k packets   */
#define LPA_PAUSE_CAP                (0x0400U) /* Can pause                   */
#define LPA_PAUSE_ASYM               (0x0800U) /* Can pause asymetrically     */
#define LPA_RESV                     (0x1000U) /* Unused...                   */
#define LPA_RFAULT                   (0x2000U) /* Link partner faulted        */
#define LPA_LPACK                    (0x4000U) /* Link partner acked us       */
#define LPA_NPAGE                    (0x8000U) /* Next page bit               */

#define LPA_DUPLEX                   (LPA_10FULL | LPA_100FULL)
#define LPA_100                      (LPA_100FULL | LPA_100HALF | LPA_100BASE4)

/* Expansion register for auto-negotiation. */
#define EXPANSION_NWAY               (0X0001U) /* Can do N-way auto-nego      */
#define EXPANSION_LCWP               (0X0002U) /* Got new RX page code word   */
#define EXPANSION_ENABLENPAGE        (0X0004U) /* This enables npage words    */
#define EXPANSION_NPCAPABLE          (0X0008U) /* Link partner supports npage */
#define EXPANSION_MFAULTS            (0X0010U) /* Multiple faults detected    */
#define EXPANSION_RESV               (0XFFE0U) /* Unused...                   */

#define ESTATUS_1000_TFULL           (0x2000U) /* Can do 1000BT Full */
#define ESTATUS_1000_THALF           (0x1000U) /* Can do 1000BT Half */

/* N-way test register. */
#define NWAYTEST_RESV1               (0X00FFU) /* Unused...                   */
#define NWAYTEST_LOOPBACK            (0X0100U) /* Enable loopback for N-way   */
#define NWAYTEST_RESV2               (0XFE00U) /* Unused...                   */

/* 1000BASE-T Control register */
#define ADVERTISE_1000FULL           (0x0200U) /* Advertise 1000BASE-T full duplex */
#define ADVERTISE_1000HALF           (0x0100U) /* Advertise 1000BASE-T half duplex */

/* 1000BASE-T Status register */
#define LPA_1000LOCALRXOK            (0x2000U) /* Link partner local receiver status */
#define LPA_1000REMRXOK              (0x1000U) /* Link partner remote receiver status */
#define LPA_1000FULL                 (0x0800U) /* Link partner 1000BASE-T full duplex */
#define LPA_1000HALF                 (0x0400U) /* Link partner 1000BASE-T half duplex */

/* Indicates what features are supported by the interface. */
#define SUPPORTED_10baseT_Half       (1U << 0)
#define SUPPORTED_10baseT_Full       (1U << 1)
#define SUPPORTED_100baseT_Half      (1U << 2)
#define SUPPORTED_100baseT_Full      (1U << 3)
#define SUPPORTED_1000baseT_Half     (1U << 4)
#define SUPPORTED_1000baseT_Full     (1U << 5)
#define SUPPORTED_Autoneg            (1U << 6)
#define SUPPORTED_TP                 (1U << 7)
#define SUPPORTED_AUI                (1U << 8)
#define SUPPORTED_MII                (1U << 9)
#define SUPPORTED_FIBRE              (1U << 10)
#define SUPPORTED_BNC                (1U << 11)
#define SUPPORTED_10000baseT_Full    (1U << 12)
#define SUPPORTED_Pause              (1U << 13)
#define SUPPORTED_Asym_Pause         (1U << 14)
#define SUPPORTED_2500baseX_Full     (1U << 15)
#define SUPPORTED_Backplane          (1U << 16)
#define SUPPORTED_1000baseKX_Full    (1U << 17)
#define SUPPORTED_10000baseKX4_Full  (1U << 18)
#define SUPPORTED_10000baseKR_Full   (1U << 19)
#define SUPPORTED_10000baseR_FEC     (1U << 20)

/* Indicates what features are advertised by the interface. */
#define ADVERTISED_10baseT_Half      (1U << 0)
#define ADVERTISED_10baseT_Full      (1U << 1)
#define ADVERTISED_100baseT_Half     (1U << 2)
#define ADVERTISED_100baseT_Full     (1U << 3)
#define ADVERTISED_1000baseT_Half    (1U << 4)
#define ADVERTISED_1000baseT_Full    (1U << 5)
#define ADVERTISED_Autoneg           (1U << 6)
#define ADVERTISED_TP                (1U << 7)
#define ADVERTISED_AUI               (1U << 8)
#define ADVERTISED_MII               (1U << 9)
#define ADVERTISED_FIBRE             (1U << 10)
#define ADVERTISED_BNC               (1U << 11)
#define ADVERTISED_10000baseT_Full   (1U << 12)
#define ADVERTISED_Pause             (1U << 13)
#define ADVERTISED_Asym_Pause        (1U << 14)
#define ADVERTISED_2500baseX_Full    (1U << 15)
#define ADVERTISED_Backplane         (1U << 16)
#define ADVERTISED_1000baseKX_Full   (1U << 17)
#define ADVERTISED_10000baseKX4_Full (1U << 18)
#define ADVERTISED_10000baseKR_Full  (1U << 19)
#define ADVERTISED_10000baseR_FEC    (1U << 20)

/* TI DP83867 PHY Control Register */

#define PHYCR_TX_FIFO_DEPTH          (0xC000U)
#define PHYCR_RX_FIFO_DEPTH          (0x3000U)
#define PHYCR_SGMII_EN               (0x0800U)
#define PHYCR_FORCE_LINK_GOOD        (0x0400U)
#define PHYCR_POWER_SAVE_MODE        (0x0300U)
#define PHYCR_DEEP_POWER_DOWN_EN     (0x0080U)
#define PHYCR_MDI_CROSSOVER          (0x0060U)
#define PHYCR_DISABLE_CLK_125        (0x0010U)
#define PHYCR_STANDBY_MODE           (0x0004U)
#define PHYCR_LINE_DRIVER_INV_EN     (0x0002U)
#define PHYCR_DISABLE_JABBER         (0x0001U)

/* TI DP83867 Control Register */

#define CTRL_SW_RESET                (0x8000U)
#define CTRL_SW_RESTART              (0x4000U)

/* TI DP83867 SGMII Control Register 1 */

#define SGMII_TYPE_6_WIRE            (0x4000U)

/* Different PHY MDIO addresses for our current designs */

#if defined(TARGET_ALOE)
#define PHY_VSC8541_MDIO_ADDR (0U) /* Aloe board PHY */
#else
#define PHY_VSC8541_MDIO_ADDR (26U) /* SVG MSS board PHY */
#endif
#define PHY_VSC8662_0_MDIO_ADDR (8U) /* SVG MSS board port 0 */
#define PHY_VSC8662_1_MDIO_ADDR (9U) /* SVG MSS board port 1 */
#define PHY_VSC8575_MDIO_ADDR   (4U) /* G5 SoC Emulation Platform Peripheral Daughter Board PHY */
#define PHY_DP83867_MDIO_ADDR   (3U) /* G5 SoC Emulation Platform native PHY */
#define PHY_RTL8211_MDIO_ADDR   (1U) /* G5 SoC BeagleV-Fire PHY */
#define PHY_NULL_MDIO_ADDR      (0U) /* No PHY here actually... */
#define SGMII_MDIO_ADDR         (16U) /* Internal PHY in G5 SoC Emulation Platform SGMII to GMII core */

/**************************************************************************/
/* Public function declarations                                           */
/**************************************************************************/

/***************************************************************************/ /**
   void MSS_MAC_phy_init(mss_mac_instance_t *this_mac, uint8_t phy_addr);
  */
#if MSS_MAC_USE_PHY_VSC8541
void MSS_MAC_VSC8541_phy_init(/* mss_mac_instance_t */ const void *v_this_mac, uint8_t phy_addr);
#endif

#if MSS_MAC_USE_PHY_VSC8575 || MSS_MAC_USE_PHY_VSC8575_LITE
void MSS_MAC_VSC8575_phy_init(/* mss_mac_instance_t */ const void *v_this_mac, uint8_t phy_addr);
#endif

#if MSS_MAC_USE_PHY_VSC8662
void MSS_MAC_VSC8662_phy_init(/* mss_mac_instance_t */ const void *v_this_mac, uint8_t phy_addr);
#endif

#if MSS_MAC_USE_PHY_DP83867
void MSS_MAC_DP83867_phy_init(/* mss_mac_instance_t */ const void *v_this_mac, uint8_t phy_addr);
#endif

#if MSS_MAC_USE_PHY_NULL
void MSS_MAC_NULL_phy_init(/* mss_mac_instance_t */ const void *v_this_mac, uint8_t phy_addr);
#endif

#if MSS_MAC_USE_PHY_RTL8211
void MSS_MAC_RTL8211_phy_init(/* mss_mac_instance_t */ const void *v_this_mac, uint8_t phy_addr);
#endif

/***************************************************************************/ /**

  */
#if MSS_MAC_USE_PHY_VSC8541
void MSS_MAC_VSC8541_phy_set_link_speed(/* mss_mac_instance_t*/ void *v_this_mac,
                                        uint32_t speed_duplex_select,
                                        mss_mac_speed_mode_t speed_mode);
#endif

#if MSS_MAC_USE_PHY_VSC8575 || MSS_MAC_USE_PHY_VSC8575_LITE
void MSS_MAC_VSC8575_phy_set_link_speed(/* mss_mac_instance_t */ void *v_this_mac,
                                        uint32_t speed_duplex_select,
                                        mss_mac_speed_mode_t speed_mode);
#endif

#if MSS_MAC_USE_PHY_VSC8662
void MSS_MAC_VSC8662_phy_set_link_speed(/* mss_mac_instance_t */ void *v_this_mac,
                                        uint32_t speed_duplex_select,
                                        mss_mac_speed_mode_t speed_mode);
#endif

#if MSS_MAC_USE_PHY_DP83867
void MSS_MAC_DP83867_phy_set_link_speed(/* mss_mac_instance_t */ void *v_this_mac,
                                        uint32_t speed_duplex_select,
                                        mss_mac_speed_mode_t speed_mode);
#endif

#if MSS_MAC_USE_PHY_NULL
void MSS_MAC_NULL_phy_set_link_speed(/* mss_mac_instance_t */ void *v_this_mac,
                                     uint32_t speed_duplex_select,
                                     mss_mac_speed_mode_t speed_mode);
#endif

#if MSS_MAC_USE_PHY_RTL8211
void MSS_MAC_RTL8211_phy_set_link_speed(/* mss_mac_instance_t */ void *v_this_mac,
                                        uint32_t speed_duplex_select,
                                        mss_mac_speed_mode_t speed_mode);
#endif

/***************************************************************************/ /**

  */
#if MSS_MAC_USE_PHY_VSC8541
void MSS_MAC_VSC8541_phy_autonegotiate(/* mss_mac_instance_t */ const void *v_this_mac);
void MSS_MAC_VSC8541_mac_autonegotiate(/* mss_mac_instance_t */ const void *v_this_mac);
#endif

#if MSS_MAC_USE_PHY_VSC8575 || MSS_MAC_USE_PHY_VSC8575_LITE
void MSS_MAC_VSC8575_phy_autonegotiate(/* mss_mac_instance_t */ const void *v_this_mac);
void MSS_MAC_VSC8575_mac_autonegotiate(/* mss_mac_instance_t */ const void *v_this_mac);
#endif

#if MSS_MAC_USE_PHY_VSC8662
void MSS_MAC_VSC8662_phy_autonegotiate(/* mss_mac_instance_t */ const void *v_this_mac);
void MSS_MAC_VSC8662_mac_autonegotiate(/* mss_mac_instance_t */ const void *v_this_mac);
#endif

#if MSS_MAC_USE_PHY_DP83867
void MSS_MAC_DP83867_phy_autonegotiate(/* mss_mac_instance_t */ const void *v_this_mac);
void MSS_MAC_DP83867_mac_autonegotiate(/* mss_mac_instance_t */ const void *v_this_mac);

#endif

#if MSS_MAC_USE_PHY_NULL
void MSS_MAC_NULL_phy_autonegotiate(/* mss_mac_instance_t */ const void *v_this_mac);
void MSS_MAC_NULL_phy_mac_autonegotiate(/* mss_mac_instance_t */ const void *v_this_mac);
#endif

#if MSS_MAC_USE_PHY_RTL8211
void MSS_MAC_RTL8211_phy_autonegotiate(/* mss_mac_instance_t */ const void *v_this_mac);
void MSS_MAC_RTL8211_mac_autonegotiate(/* mss_mac_instance_t */ const void *v_this_mac);
#endif

/***************************************************************************/ /**

  */

#if MSS_MAC_USE_PHY_VSC8541
uint8_t MSS_MAC_VSC8541_phy_get_link_status(
    /* mss_mac_instance_t */ const void *v_this_mac,
    mss_mac_speed_t *speed,
    uint8_t *fullduplex);
#endif

#if MSS_MAC_USE_PHY_VSC8575 || MSS_MAC_USE_PHY_VSC8575_LITE
uint8_t MSS_MAC_VSC8575_phy_get_link_status(
    /* mss_mac_instance_t */ const void *v_this_mac,
    mss_mac_speed_t *speed,
    uint8_t *fullduplex);
#endif

#if MSS_MAC_USE_PHY_VSC8662
uint8_t MSS_MAC_VSC8662_phy_get_link_status(
    /* mss_mac_instance_t */ const void *v_this_mac,
    mss_mac_speed_t *speed,
    uint8_t *fullduplex);
#endif

#if MSS_MAC_USE_PHY_DP83867
uint8_t MSS_MAC_DP83867_phy_get_link_status(
    /* mss_mac_instance_t */ const void *v_this_mac,
    mss_mac_speed_t *speed,
    uint8_t *fullduplex);
#endif

#if MSS_MAC_USE_PHY_NULL
uint8_t MSS_MAC_NULL_phy_get_link_status(
    /* mss_mac_instance_t */ const void *v_this_mac,
    mss_mac_speed_t *speed,
    uint8_t *fullduplex);
#endif

#if MSS_MAC_USE_PHY_RTL8211
uint8_t MSS_MAC_RTL8211_phy_get_link_status(
    /* mss_mac_instance_t */ const void *v_this_mac,
    mss_mac_speed_t *speed,
    uint8_t *fullduplex);
#endif

#if MSS_MAC_USE_PHY_DP83867
/***************************************************************************/ /**

  */
void mmd_write_extended_regs(/* mss_mac_instance_t */ const void *v_this_mac,
                             uint16_t dev,
                             uint16_t reg,
                             uint16_t data);

/***************************************************************************/ /**

  */
uint16_t mmd_read_extended_regs(/* mss_mac_instance_t */ const void *v_this_mac,
                                uint16_t dev,
                                uint16_t reg);

#endif

/*------------------------------------------------------------------------------
 * These always need to be defined as they are the safe fillers for PHYs that
 * don't support MMD register access.
 */
uint16_t NULL_mmd_read_extended_regs(/* mss_mac_instance_t */ const void *v_this_mac,
                                     uint16_t dev,
                                     uint16_t reg);
void NULL_mmd_write_extended_regs(/* mss_mac_instance_t */ const void *v_this_mac,
                                  uint16_t dev,
                                  uint16_t reg,
                                  uint16_t data);

#ifdef __cplusplus
}
#endif

#endif /* PSE_PHY_H */
